package de.fhluebeck.oop.gps.common;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Properties;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import de.fhluebeck.oop.gps.common.exception.DependencyResolveException;
import de.fhluebeck.oop.gps.common.util.PropertiesHelper;

/**
 * Diese Klasse stellt den DependencyManager dar.
 * Durch Aufruf der Methode locate wird eine Klasse vom Type "type" instanziiert
 * oder, falls diese Klasse das Interface Singleton implementiert, ruft sie die 
 * statische Methode "getInstance" auf.
 *  
 * @author Ogün Bilge, Leif Hitzschke
 * @version 1.00, 13.11.2009
 * 
 */
public class DependencyManager {

	private final static Logger log = LoggerFactory
			.getLogger(DependencyManager.class);

	public static Object locate(String type) {
				try {
			Properties props = PropertiesHelper.loadDependencyProperties();
			String clazzName = props.getProperty(type);
			Class clazz = Class.forName(clazzName);
			
			if(Singleton.class.isAssignableFrom(clazz)) {
				Method method = clazz.getDeclaredMethod("getInstance");
				// invoke static method
				log.debug("invoking getInstance on {}" , clazz);
				return method.invoke(null);
			}else {
				// create new instance of clazz
				
				log.debug("creating new instance of {}" , clazz);
				return clazz.newInstance();
			}
			
		} catch (ClassNotFoundException e) {
			log.error("", e);
			throw new DependencyResolveException(
					"Could not resolve dependency", e);
		} catch (InstantiationException e) {
			log.error("", e);
			throw new DependencyResolveException(
					"Could not resolve dependency", e);
		} catch (IllegalAccessException e) {
			log.error("", e);
			throw new DependencyResolveException(
					"Could not resolve dependency", e);
		} catch (IllegalArgumentException e) {
			log.error("", e);
			throw new DependencyResolveException(
					"Could not resolve dependency", e);
		} catch (InvocationTargetException e) {
			log.error("", e);
			throw new DependencyResolveException(
					"Could not resolve dependency", e);
		} catch (SecurityException e) {
			log.error("", e);
			throw new DependencyResolveException(
					"Could not resolve dependency", e);
		} catch (NoSuchMethodException e) {
			log.error("", e);
			throw new DependencyResolveException(
					"Could not resolve dependency", e);
		}

	}

}
